
#include <pthread.h>

#include "concurrent_queue.h"
#include "public_share.h"

bool cqInitQueue(struct conQueue *queue) {
    if (!queue) return false;
    struct nodeStr *node = malloc(sizeof(struct nodeStr));
    if (!node) FATAL_ERROR("init queue malloc failed");

    node->next = NULL;
    queue->head = queue->tail = node;
    if (pthread_spin_init(&queue->headLock, PTHREAD_PROCESS_PRIVATE))
        FATAL_ERROR("Init head spinlock failed");
    if (pthread_spin_init(&queue->tailLock, PTHREAD_PROCESS_PRIVATE))
        FATAL_ERROR("Init tail spinlock failed");
    return true;
}

bool cqDestroyQueue(struct conQueue *queue) {
    if (!queue || !queue->head || queue->head != queue->tail)
        return false;
    free(queue->head);
    queue->head = queue->tail = NULL;
    pthread_spin_destroy(&queue->headLock);
    pthread_spin_destroy(&queue->tailLock);
    return true;
}

bool cqEnqueue(struct conQueue *queue, ELEMENT_TYPE val) {
    if (!queue) return false;
    struct nodeStr *node = malloc(sizeof(struct nodeStr));
    if (!node) FATAL_ERROR("enqueue malloc failed");
    node->next = NULL;
    node->value = val;
    pthread_spin_lock(&queue->tailLock);
    queue->tail = queue->tail->next = node;
    pthread_spin_unlock(&queue->tailLock);
    return true;
}

bool cqDequeue(struct conQueue *queue, ELEMENT_TYPE *val) {
    if (!queue || !val) return false;
    pthread_spin_lock(&queue->headLock);
    struct nodeStr *node = queue->head;
    if (!node->next) {
        pthread_spin_unlock(&queue->headLock);
        return false;
    }
    *val = node->next->value;
    queue->head = node->next;
    pthread_spin_unlock(&queue->headLock);
    free(node);
    return true;
}